package org.whmmm.util.office.util;

import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

/**
 * <b>此类中方法会将 excel 数据一次加载到内存,如果数据量太大,需要注意内存使用情况.</b> <br/>
 * poi excel 读取 <br/>
 * <b>使用了 poi ,poi 版本为 3.17 注意冲突</b> <br/>
 *
 * @author whmmm
 */
public class ExcelReaderUtils {

    /**
     * 加载 excel 数据到 内存 <br/>
     * 读取excel 第1张sheet （xls和xlsx）
     *
     * @param filePath excel路径
     * @param columns  列名（表头）
     * @return
     * @author lizixiang ,2018-05-08
     */
    public static List<Map<String, String>> readExcel(String filePath, String[] columns) {
        Sheet sheet = null;
        Row row = null;
        Row rowHeader = null;
        List<Map<String, String>> list = null;
        String cellData = null;
        Workbook wb = null;
        if (filePath == null) {
            return null;
        }
        String extString = filePath.substring(filePath.lastIndexOf("."));
        InputStream is = null;
        try {
            is = new FileInputStream(filePath);
            if (".xls".equals(extString)) {
                wb = new HSSFWorkbook(is);
            } else if (".xlsx".equals(extString)) {
                wb = new XSSFWorkbook(is);
            }
            if (wb != null) {
                // 用来存放表中数据
                list = new ArrayList<Map<String, String>>();
                // 获取第一个sheet
                sheet = wb.getSheetAt(0);

                // 获取最大行数
                int rownum = sheet.getPhysicalNumberOfRows();
                // 获取第一行
                rowHeader = sheet.getRow(0);
                row = sheet.getRow(0);
                // 获取最大列数
                int colnum = row.getPhysicalNumberOfCells();
                for (int i = 1; i < rownum; i++) {
                    Map<String, String> map = new LinkedHashMap<String, String>();
                    row = sheet.getRow(i);
                    if (row != null) {
                        for (int j = 0; j < colnum; j++) {
                            if (columns[j].equals(getCellFormatValue(rowHeader.getCell(j)))) {
                                cellData = (String) getCellFormatValue(row
                                        .getCell(j));
                                map.put(columns[j], cellData);
                            }
                        }
                    } else {
                        break;
                    }
                    list.add(map);
                }
            }
        } catch (FileNotFoundException e) {
            throw new RuntimeException(e);
        } catch (IOException e) {
            throw new RuntimeException(e);
        } finally {
            try {
                if (is != null) {
                    is.close();
                }
            } catch (IOException ignore) {
                // do nothing
            }
        }
        return list;
    }

    /**
     * 加载 excel 数据到 内存
     *
     * @param filePath         文件路径
     * @param columnIndex      标头索引, 从 0 开始算起! 如果 是 第一行,则填写 0
     * @param activeSheetIndex 选择的 excel sheet索引,从 0开始
     * @return
     */
    public static List<Map<String, String>> readExcel(String filePath, int columnIndex, int activeSheetIndex) {
        Sheet sheet = null;
        Row row = null;
        Row rowHeader = null;
        List<Map<String, String>> list = null;
        String cellData = null;
        Workbook wb = null;
        if (filePath == null) {
            return null;
        }
        String extString = filePath.substring(filePath.lastIndexOf("."));
        InputStream is = null;
        try {
            is = new FileInputStream(filePath);
            if (".xls".equals(extString)) {
                wb = new HSSFWorkbook(is);
            } else if (".xlsx".equals(extString)) {
                wb = new XSSFWorkbook(is);
            }
            if (wb != null) {
                // 用来存放表中数据
                list = new ArrayList<Map<String, String>>();
                // 获取第一个sheet
                sheet = wb.getSheetAt(activeSheetIndex);
                // 获取最大行数
                int rownum = sheet.getPhysicalNumberOfRows();
                // 获取第一行
                rowHeader = sheet.getRow(columnIndex);

                List<String> columns = new ArrayList<String>();

                // 获取最大列数
                int column = rowHeader.getPhysicalNumberOfCells();
                for (int i = 0; i < column; i++) {
                    columns.add(getCellFormatValue(rowHeader.getCell(i)).toString());
                }


                row = sheet.getRow(0);

                for (int i = columnIndex + 1; i < rownum; i++) {
                    Map<String, String> map = new LinkedHashMap<String, String>();
                    row = sheet.getRow(i);
                    if (row != null) {
                        for (int j = 0; j < column; j++) {
                            if (columns.get(j).equals(getCellFormatValue(rowHeader.getCell(j)))) {
                                cellData = (String) getCellFormatValue(row
                                        .getCell(j));
                                map.put(columns.get(j), cellData);
                            }
                        }
                    } else {
                        break;
                    }
                    list.add(map);
                }
            }
        } catch (FileNotFoundException e) {
            throw new RuntimeException(e);
        } catch (IOException e) {
            throw new RuntimeException(e);
        } finally {
            try {
                if (is != null) {
                    is.close();
                }
            } catch (IOException ignore) {
                // do nothing
            }
        }
        return list;


    }

    /**
     * 加载 excel 数据到 内存
     *
     * @param filePath
     * @param columnIndex
     * @return
     * @see #readExcel(String, int, int)
     */
    public static List<Map<String, String>> readExcel(String filePath, int columnIndex) {
        return readExcel(filePath, columnIndex, 0);
    }

    /**
     * 加载 excel 数据到 内存
     *
     * @param filePath
     * @return
     * @see #readExcel(String, int, int)
     */
    public static List<Map<String, String>> readExcel(String filePath) {
        return readExcel(filePath, 0, 0);
    }

    /**
     * 获取单个单元格数据 ,返回 string 类型,并且去除了 左右的空格
     *
     * @param cell
     * @return
     * @author lizixiang ,2018-05-08
     */
    public static String  getCellFormatValue(Cell cell) {
        Object cellValue = null;
        if (cell != null) {
            // 判断cell类型
            switch (cell.getCellType()) {
                case Cell.CELL_TYPE_NUMERIC: {
                    cellValue = String.valueOf(cell.getNumericCellValue());
                    break;
                }
                case Cell.CELL_TYPE_FORMULA: {
                    // 判断cell是否为日期格式
                    if (DateUtil.isCellDateFormatted(cell)) {
                        // 转换为日期格式YYYY-mm-dd
                        cellValue = cell.getDateCellValue();
                    } else {
                        // 数字
                        cellValue = String.valueOf(cell.getNumericCellValue());
                    }
                    break;
                }
                case Cell.CELL_TYPE_STRING: {
                    cellValue = cell.getRichStringCellValue().getString();
                    break;
                }
                default:
                    cellValue = "";
            }
        } else {
            cellValue = "";
        }

        if (cellValue == null) {
            cellValue = "";
        }

        return cellValue.toString().trim();
    }

}